#!/usr/bin/env python
# -*- coding: UTF-8 -*-

'''
Copyright (C) 2009 dbzhang800@gmail.com
All rights reserved.
''' 

import ctypes
from ctypes.wintypes import *

CR_SUCCESS = 0x00000000
CM_DRP_DRIVER = 0x0000000A
CM_DRP_DEVICEDESC = 0x00000001
NULL = 0

cfgmgr32 = ctypes.windll.cfgmgr32
CM_Locate_DevNode = cfgmgr32.CM_Locate_DevNodeW
#CM_Locate_DevNode.argtypes = [ctypes.c_void_p , LPWSTR, ULONG]
CM_Locate_DevNode.argtypes = [ctypes.c_void_p , ctypes.c_void_p, ULONG]
CM_Locate_DevNode.restype = DWORD
CM_Get_DevNode_Registry_Property = cfgmgr32.CM_Get_DevNode_Registry_PropertyW
CM_Get_DevNode_Registry_Property.argtypes = [DWORD, ULONG, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ULONG]
CM_Get_DevNode_Registry_Property.restype = DWORD
CM_Get_Child = cfgmgr32.CM_Get_Child
CM_Get_Child.argtypes = [ctypes.c_void_p, DWORD, ULONG]
CM_Get_Child.restype = DWORD
CM_Get_Sibling = cfgmgr32.CM_Get_Sibling
CM_Get_Sibling.argtypes = [ctypes.c_void_p, DWORD, ULONG]
CM_Get_Sibling.restype = DWORD
CM_Get_Parent = cfgmgr32.CM_Get_Parent
CM_Get_Parent.argtypes = [ctypes.c_void_p, DWORD, ULONG]
CM_Get_Parent.restype = DWORD
CM_Get_Device_ID = cfgmgr32.CM_Get_Device_IDW


# this function not work well
def driverNameToDeviceDesc(driverName, deviceId):
    devInst = DWORD()
    devInstNext = DWORD()
    
    cr = CM_Locate_DevNode(ctypes.byref(devInst), NULL, 0)
    if cr != CR_SUCCESS:
        exit(1)
    
    #buf = ctypes.create_string_buffer(260)
    buf = ctypes.create_unicode_buffer(260)
    walkDone = False
    while (not walkDone):
        buf_length = ULONG(buf._length_)
        cr = CM_Get_DevNode_Registry_Property(
                devInst,
                CM_DRP_DRIVER,
                NULL,
                buf, 
                ctypes.byref(buf_length),
                0)
        if cr == CR_SUCCESS and driverName == buf.value:
            #print buf.value
            #print [ord(i) for i in buf[:10]] 
            if deviceId:
                cr = CM_Get_Device_ID(devInst, buf, buf_length, 0)
            else:
                cr = CM_Get_DevNode_Registry_Property(
                        devInst,
                        CM_DRP_DEVICEDESC,
                        NULL,
                        buf,
                        ctypes.byref(buf_length),
                        0)
            if cr == CR_SUCCESS:
                #print buf.value
                #print [ord(i) for i in buf[:10]] 
                return buf.value
    
    
        cr = CM_Get_Child(ctypes.byref(devInstNext), devInst, 0)
        if cr == CR_SUCCESS:
            devInst = devInstNext
            continue
    
        while True:
            cr = CM_Get_Sibling(ctypes.byref(devInstNext), devInst, 0)
            if cr == CR_SUCCESS:
                devInst = devInstNext
                break;
    
            cr = CM_Get_Parent(ctypes.byref(devInstNext), devInst, 0)
            if cr == CR_SUCCESS:
                devInst = devInstNext;
            else:
                walkDone = 1;
                break;

if __name__ == '__main__':
   print driverNameToDeviceDesc(r'{4d36e972-e325-11ce-bfc1-08002be10318}\0020', True); 
   print driverNameToDeviceDesc(r'{4d36e972-e325-11ce-bfc1-08002be10318}\0020', False); 
   print driverNameToDeviceDesc(r'{36fc9e60-c465-11cf-8056-444553540000}\0003', True); 
   print driverNameToDeviceDesc(r'{36fc9e60-c465-11cf-8056-444553540000}\0003', False); 
